/*****************************************************************************
  Copyright ?2002-2004 by Martin Cook. All rights are reserved. If you like
  this code then feel free to go ahead and use it. The only thing I ask is 
  that you don't remove or alter my copyright notice. Your use of this 
  software is entirely at your own risk. I make no claims about the 
  reliability or fitness of this code for any particular purpose. If you 
  make changes or additions to this code then please clearly mark your code 
  as yours. If you have questions or comments then please contact me at: 
  martin@codegator.com
  
  Have Fun! :o)
*****************************************************************************/

using System;
using System.Reflection;
using System.IO;

using CG.Security.Configuration;
using CG.Security.Data.Configuration;

namespace CG.Security.Data
{
	/// <summary>
	/// Manages the creation of data objects.
	/// </summary>
	internal sealed class DataManager
	{

		// ******************************************************************
		// Properties.
		// ******************************************************************

		#region Properties

		/// <summary>
		/// Gets a SecurityData object.
		/// </summary>
		public static ISecurityData SecurityData
		{
			get {return (ISecurityData)_CreateDataObject("SecurityData");}
		} // End UserData

		// ******************************************************************

		/// <summary>
		/// Gets a UserData object.
		/// </summary>
		public static IUserData UserData
		{
			get {return (IUserData)_CreateDataObject("UserData");}
		} // End UserData

		// ******************************************************************

		/// <summary>
		/// Gets a RoleData object.
		/// </summary>
		public static IRoleData RoleData
		{
			get {return (IRoleData)_CreateDataObject("RoleData");}
		} // End RoleData

		// ******************************************************************

		/// <summary>
		/// Gets a UserRoleData object.
		/// </summary>
		public static IUserRoleData UserRoleData
		{
			get {return (IUserRoleData)_CreateDataObject("UserRoleData");}
		} // End UserRoleData

		// ******************************************************************

		/// <summary>
		/// Gets a RightData object.
		/// </summary>
		public static IRightData RightData
		{
			get {return (IRightData)_CreateDataObject("RightData");}
		} // End RightData

		// ******************************************************************

		/// <summary>
		/// Gets a UserRightData object.
		/// </summary>
		public static IUserRightData UserRightData
		{
			get {return (IUserRightData)_CreateDataObject("UserRightData");}
		} // End UserRightData

		// ******************************************************************

		/// <summary>
		/// Gets a RoleRightData object.
		/// </summary>
		public static IRoleRightData RoleRightData
		{
			get {return (IRoleRightData)_CreateDataObject("RoleRightData");}
		} // End RoleRightData

		#endregion

		// ******************************************************************
		// Private methods.
		// ******************************************************************

		#region Private methods

		/// <summary>
		/// Create a new data access object, using the configuration 
		/// settings retrieved from the CG.Security.Data/runtimeSetup 
		/// configuration section.
		/// </summary>
		/// <param name="className">The name of the class to create.</param>
		/// <returns></returns>
		private static object _CreateDataObject(string className)
		{
	
            // Note: This method could be made faster by caching the
			//   results of the reflection lookups. After all, once
			//   the assembly is located and loaded for the first 
			//   why go through all that work again?

			// Should we format the class name for reflection lookups?
			if (!className.StartsWith("."))
				className = "." + className;

			// Read the runtime setup.
			DataSettings ds = SettingsManager.DataSettings;

			Assembly assembly = null;
			object dal = null;

			// Start by using the executing assembly.
			assembly = Assembly.GetExecutingAssembly();

			// Attemp to create the data object.
			dal = assembly.CreateInstance(
				ds.TargetNamespace + 
				className
				);

			// Did we fail?
			if (dal == null)
			{

				// Attempt to load an external assembly using the namespace.
				assembly = Assembly.Load(ds.TargetAssembly);

				// Attemp to create the data object.
				dal = assembly.CreateInstance(
					ds.TargetNamespace + 
					className
					);

				// Did we fail?
				if (dal == null)
					throw new Exception(
						"Failed to create a " + 
						ds.TargetNamespace + 
						className + 
						" instance!"
						);

			} // End if we failed to load the class externally

			// Return the data object.
			return dal;

		} // End _CreateDataObject()

		#endregion

	} // End class DataManager

} // End namespace CG.Security.Data


